package cz.semjobKB.conllx.api.impl;

import java.util.ArrayList;
import java.util.List;

import cz.semjobKB.conllx.api.ETextPart;
import cz.semjobKB.conllx.api.IParagraph;
import cz.semjobKB.conllx.api.ISentence;
import cz.semjobKB.conllx.api.ITextPart;

/**
 * Paragraph class provides methods to operate with the document tree on a
 * paragraph level
 */
public class Paragraph implements IParagraph {

	/**
	 * serialization
	 */
	private static final long serialVersionUID = 4819383942505205598L;

	/** The sentences. */
	private final List<Sentence> sentences;

	/** The root. */
	private final Document root;

	/** The current sentence index. */
	protected int currentSentenceIndex;

	/** The next paragraph reference. */
	private Paragraph nextParagraph = null;

	/** The previous paragraph. */
	private Paragraph previousParagraph = null;

	/** The original text. */
	private String text = null;

	/**
	 * Instantiates a new paragraph.
	 * 
	 * @param belongsToDocument
	 *            The root document
	 */
	public Paragraph(final Document belongsToDocument) {
		root = belongsToDocument;
		sentences = new ArrayList<Sentence>();
	}

	
	public void setNextParagraph(final IParagraph next) {
		nextParagraph = (Paragraph) next;
	}

	/**
	 * Gets the next paragraph.
	 * 
	 * @return the next paragraph
	 */
	public Paragraph getNextParagraph() {
		return nextParagraph;
	}

	/**
	 * Gets the previous paragraph.
	 * 
	 * @return the previous paragraph
	 */
	public Paragraph getPreviousParagraph() {
		return previousParagraph;
	}

	/**
	 * Sets the previous paragraph.
	 * 
	 * @param previousParagraph
	 *            the new previous paragraph
	 */
	public void setPreviousParagraph(final Paragraph previousParagraph) {
		this.previousParagraph = previousParagraph;
	}

	
	public String getText() {		
		return text;
	}

	
	public boolean hasNext(final ETextPart part) {
		if (part == ETextPart.WORD) {
			ISentence sentence = sentences.get(root.selectedSentence);
			if (sentence.hasNext(part)) {
				return true;
			} else {
				root.selectedSentence++;
				if (sentence.hasNext(ETextPart.SENTENCE)) {
					return true;
				}
			}
			return false;
		}
		if (part == ETextPart.SENTENCE) {
			if (root.selectedSentence >= getSentences().size()) {
				return false;
			}
			if (sentences.get(root.selectedSentence).hasNext(part)) {
				return true;
			} else {
				return false;
			}
		}
		if (part == ETextPart.PARAGRAPH) {
			if (root.selectedParagraph < root.getParagraphs().size()) {
				return true;
			} else {
				root.reset();
				return false;
			}
		}
		return false;
	}

	
	public ITextPart getNext(final ETextPart part) {
		if (part == ETextPart.WORD) {
			Sentence sentence = sentences.get(root.selectedSentence);
			if (sentence.hasNext(part)) {
				return sentence.getNext(part);
			} else {
				if (sentence.hasNext(ETextPart.SENTENCE)) {
					sentence = (Sentence) sentence.getNext(ETextPart.SENTENCE);
					return sentence.getNext(part);
				}
			}
			return null;
		}
		if (part == ETextPart.SENTENCE) {
			if (sentences.get(root.selectedSentence).hasNext(part)) {
				Sentence sentence = (Sentence) sentences.get(root.selectedSentence).getNext(part);
				return sentence;
			} else {
				return null;
			}
		}
		if (part == ETextPart.PARAGRAPH) {
			if (hasNext(part)) {
				root.selectedParagraph++;
				root.selectedSentence = 0;
				root.selectedWord = 0;
				return this;
			} else {
				root.reset();
				return null;
			}
		}
		return null;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Sentence> getSentences() {
		return sentences;
	}

	/**
	 * Gets the sentence.
	 * 
	 * @param index the position of the sentence in this paragraph            
	 * @return the sentence
	 */
	public Sentence getSentence(final int index) {
		return sentences.get(index);
	}

	/**
	 * Sets the text.
	 * 
	 * @param text
	 *            the new text
	 */
	public void setText(final String text) {
		this.text = text;
	}

	/**
	 * Adds all sentences of the paragraph
	 * 
	 * @param sentences
	 *            the sentences
	 */
	public void addAllSentences(final List<Sentence> sentences) {
		this.sentences.addAll(sentences);
	}

	/**
	 * Gets the sentence count.
	 * 
	 * @return the sentence count
	 */
	public int getSentenceCount() {
		return this.sentences.size();
	}
	
	
	public String toString() {
		return "Paragraph [text=" + getText() + "]";
	}
}
